﻿''' <summary>
''' This class implements a .Net assembly collector.
''' </summary>
''' <remarks>
''' The purpose of the .Net assembly collector is to read assemblies
''' that are specified in the configuration and output the full
''' assembly name to the system info report.
''' </remarks>
Public Class AssemblyCollector
    Implements ICollector

    ''' <summary>
    ''' List of writers passed when Startup() is called.
    ''' </summary>
    ''' <remarks></remarks>
    Protected m_writers As List(Of Writer.IWriter)

    ''' <summary>
    ''' List of assembly entries.
    ''' </summary>
    ''' <remarks></remarks>
    Protected m_entries As List(Of AssemblyEntry)

    ''' <summary>
    ''' This holds an error description.
    ''' </summary>
    ''' <remarks></remarks>
    Protected m_error As String

    Public Sub Cleanup() Implements ICollector.Cleanup

        'Nothing to do

    End Sub

    Public Sub Run() Implements ICollector.Run

        'Write our category name.
        Writer.WritersHelper.WriteCategory(".Net Assembly Information", m_writers)

        'If an error occurred while reading the configuration file, write
        'it out and stop here.
        If m_error <> "" Then
            Writer.WritersHelper.WriteCategoryError(m_error, m_writers)
        Else
            'Scan all assembly entries.
            For Each asm As AssemblyEntry In m_entries
                Try
                    'Write the assembly name entry.
                    Writer.WritersHelper.WriteSection(asm.Name, m_writers)
                    'Process this path.
                    ProcessDir(asm.Path, asm.FileMask, asm.Recurse)
                Catch ex As Exception
                    'Error gathering info.
                    Writer.WritersHelper.WriteSectionError("Error retrieving assembly information (" + ex.Message + ")", m_writers)
                End Try
                'Write out a blank.
                Writer.WritersHelper.WriteBlank(m_writers)
            Next
        End If

    End Sub

    Public Sub Startup(ByVal cfgFile As String, ByVal writers As System.Collections.Generic.List(Of Writer.IWriter)) Implements ICollector.Startup

        'Get all writers.
        m_writers = writers
        'Read configuration file.
        ReadConfiguration(cfgFile)

    End Sub

    ''' <summary>
    ''' Read the configuration file.
    ''' </summary>
    ''' <param name="fName">File name with assembly collector configuration.</param>
    ''' <remarks></remarks>
    Protected Sub ReadConfiguration(ByVal fName As String)

        Const ASSEMBLYPATH_TABLE As String = "AssemblyPath"

        Try
            'Read in a dataset.
            Dim ds As New DataSet
            ds.ReadXml(fName)
            m_entries = New List(Of AssemblyEntry)

            'Parse all entries.
            For i As Integer = 0 To ds.Tables(ASSEMBLYPATH_TABLE).Rows.Count - 1
                With ds.Tables(ASSEMBLYPATH_TABLE).Rows(i)
                    m_entries.Add(New AssemblyEntry(Convert.ToString(.Item("Name")), _
                                                    Convert.ToString(.Item("Path")), _
                                                    Convert.ToString(.Item("FileMask")), _
                                                    Convert.ToBoolean(.Item("Recurse"))))
                End With
            Next

            ds.Dispose()
            ds = Nothing

            'Signal no error.
            m_error = ""
        Catch ex As Exception
            'Keep the error here.
            m_error = ex.ToString()
        End Try

    End Sub

    ''' <summary>
    ''' Process a directory's .Net assemblies.
    ''' </summary>
    ''' <param name="topDir">Directory to start from.</param>
    ''' <param name="fileMask">File mask of files to look for.</param>
    ''' <param name="recurse">Recurse flag.</param>
    ''' <remarks></remarks>
    Protected Sub ProcessDir(ByVal topDir As String, ByVal fileMask As String, ByVal recurse As Boolean)

        Dim files() As String = System.IO.Directory.GetFiles(topDir, fileMask)
        For i As Integer = 0 To files.GetUpperBound(0)
            Dim FI As New System.IO.FileInfo(files(i))
            Writer.WritersHelper.WriteEntry("File", FI.FullName, m_writers)
            Try
                Dim asm As Reflection.Assembly = Reflection.Assembly.LoadFile(FI.FullName)
                Writer.WritersHelper.WriteEntry("Assembly Information", asm.FullName, m_writers)
            Catch ex As Exception
                Writer.WritersHelper.WriteEntryError("Error retrieving assembly information (" + ex.Message + ")", m_writers)
            End Try
            If i <> files.GetUpperBound(0) Then Writer.WritersHelper.WriteBlankEntry(m_writers)
        Next

        If recurse Then
            Dim dirs() As String = System.IO.Directory.GetDirectories(topDir)
            For i As Integer = 0 To dirs.GetUpperBound(0)
                ProcessDir(dirs(i), fileMask, True)
            Next
        End If

    End Sub

End Class
